/*
 * CgFlowUnit.c
 *
 *  Created on: 2012/06/07
 *      Author: guanxiaoying
 */

#include "../coredef.h"
#include "../cc/cc.h"
#include "cg.h"


static PSZ cg_setStatementLabel(AST astStmt) {
	static CHAR szLabel[_BUFFER_SIZE_+1];
	U2 kind = stStatementAccess.statmentKind.get(astStmt);
	AST astCodeScope = stStatementAccess.codeScp.get( astStmt );

	switch (kind) {
	case STMT_EXP:
		sprintf( szLabel, "_statement_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ));
		break;
	case STMT_LABEL:
		sprintf( szLabel, "_label_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_CASE:
		sprintf( szLabel, "_case_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_DEFAULT:
		sprintf( szLabel, "_default_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_BLOCK:
		sprintf( szLabel, "_block_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_IF:
		sprintf( szLabel, "_if_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_SWITCH:
		sprintf( szLabel, "_switch_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_FOR:
		sprintf( szLabel, "_for_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_WHILE:
		sprintf( szLabel, "_while_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_DO:
		sprintf( szLabel, "_do_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_GOTO:
		sprintf( szLabel, "_goto_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_BREAK:
		sprintf( szLabel, "_break_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_CONTINUE:
		sprintf( szLabel, "_continue_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_RETURN:
		sprintf( szLabel, "_return_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	case STMT_DEC:
		sprintf( szLabel, "_declaration_%ld_%ld_%ld_", astStmt, stCoreCodeScpAccess.startLine.get( astCodeScope ), stCoreCodeScpAccess.endLine.get( astCodeScope ) );
		break;
	default:
		szLabel[0]='\0';
		break;
	}
	return szLabel;
}


/***********************************
 * Command List
 ***********************************/

AST CG_NewChooseCmdList(AST astExp) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_CHOOSE );
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stExpressionAccess.codeScp.get(astExp));
//	stCmdListAccess.label.set( astCmdList, cg_setExpressionLabel(astExp) );
	return astCmdList;
}
AST CG_NewChooseEndCmdList(AST astExp) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_CHOOSEEND );
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stExpressionAccess.codeScp.get(astExp));
//	stCmdListAccess.label.set( astCmdList, cg_setExpressionLabel(astExp) );
	return astCmdList;
}

AST CG_NewCmdListByKind( U2 kind, AST astExp ){
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, kind);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stExpressionAccess.codeScp.get(astExp));
//	stCmdListAccess.label.set( astCmdList, cg_setExpressionLabel(astExp) );
	return astCmdList;
}
AST CG_NewCmdListByKind_Decl( U2 kind, AST astDecl ){
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, kind);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stDeclaratorAccess.codeScp.get(astDecl));
//	stCmdListAccess.label.set( astCmdList, cg_setExpressionLabel(astExp) );
	return astCmdList;
}
AST CG_NewConfluxCmdList(AST astStmt, PSZ postfix ) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_CONFLUX);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
	stCmdListAccess.label.set( astCmdList, strcat( cg_setStatementLabel( astStmt ), postfix ) );
	return astCmdList;
}
AST CG_NewJumpCmdList(AST astStmt) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_JUMP);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
	stCmdListAccess.label.set( astCmdList, strcat( cg_setStatementLabel( astStmt ), "jump" ) );
	return astCmdList;
}
AST CG_NewBranchCmdList(AST astStmt) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_BRANCH);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
	stCmdListAccess.label.set( astCmdList, strcat( cg_setStatementLabel( astStmt ), "branch" ) );
	return astCmdList;
}
AST CG_NewJudgeCmdList(AST astExp ) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_JUDGE);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stExpressionAccess.codeScp.get(astExp));
	return astCmdList;
}
AST CG_NewReturnCmdList(AST astStmt) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_RETURN);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
//	stCmdListAccess.label.set( astCmdList, cg_setStatementLabel(astStmt) );
	return astCmdList;
}
AST CG_NewFuncEntryCmdList(AST astStmt) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_FUNCENTRY);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
	stCmdListAccess.label.set( astCmdList, stFunctionInfoAccess.name.get( astFunc ) );
	return astCmdList;
}
AST CG_NewFuncExitCmdList(AST astStmt) {
	AST astCmdList;
	AST astFunc = CG_DeclGetCurrFunction();

	stCmdListAccess.alloc(1);
	astCmdList = stCmdListAccess.getMax();
	stCmdListAccess.opKind.set(astCmdList, ASM_CMD_FUNCEXIT);
	stCmdListAccess.function.set(astCmdList, astFunc);
	stCmdListAccess.codeScp.set(astCmdList,
			stStatementAccess.codeScp.get(astStmt));
	stCmdListAccess.label.set( astCmdList, stFunctionInfoAccess.name.get( astFunc ) );
	return astCmdList;
}
CG_RESULT CG_MergeResult( CG_RESULT a, CG_RESULT b ){
	if( a.astBegin > 0 ){
		if( b.astBegin > 0 ){
			if( stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_FUNCEXIT
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_BRANCH
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_JUMP
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_CHOOSE
				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_RETURN ){
				stCmdListAccess.next.set( a.astEnd, b.astBegin );
			}
			if(
//					stCmdListAccess.opKind.get( b.astBegin ) != ASM_CMD_CONFLUX
//				&& stCmdListAccess.opKind.get( b.astBegin ) != ASM_CMD_CHOOSEEND
//				&&
				stCmdListAccess.opKind.get( b.astBegin ) != ASM_CMD_FUNCENTRY ){
				stCmdListAccess.before.set( b.astBegin, a.astEnd );
			}
			a.astEnd = b.astEnd;
		}
	}else{
		a = b;
	}
	return a;
}
CG_RESULT CG_MergeCmdList( CG_RESULT a, AST astList ){
	if( a.astBegin > 0 ){
		if( astList > 0 ){
			if( stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_FUNCEXIT
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_BRANCH
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_JUMP
//				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_CHOOSE
				&& stCmdListAccess.opKind.get( a.astEnd ) != ASM_CMD_RETURN ){
				stCmdListAccess.next.set( a.astEnd, astList );
			}
			if(
//					stCmdListAccess.opKind.get( astList ) != ASM_CMD_CONFLUX
//				&& stCmdListAccess.opKind.get( astList ) != ASM_CMD_CHOOSEEND
//				&&
				stCmdListAccess.opKind.get( astList ) != ASM_CMD_FUNCENTRY ){
				stCmdListAccess.before.set( astList, a.astEnd );
			}
			a.astEnd = astList;
		}
	}else{
		a.astBegin = astList;
		a.astEnd = astList;
	}
	return a;
}
/***********************************
 * Operand
 ***********************************/
AST CG_NewConstantStringOperand( AST astConstantStr ){
	AST astOperand=0;
	if( astConstantStr > 0 ){
		stOperandAccess.alloc(1);
		astOperand = stOperandAccess.getMax();
		stOperandAccess.kind.set( astOperand, OPERAND_CONSTSTRING );
		stOperandAccess.parameter.set( astOperand, astConstantStr );
	}
	return astOperand;
}
AST CG_NewConstantOperand( AST astConstant ){
	AST astOperand=0;
	if( astConstant > 0 ){
		astConstant = CG_ConvertConstant( astConstant );
		stOperandAccess.alloc(1);
		astOperand = stOperandAccess.getMax();
		stOperandAccess.kind.set( astOperand, OPERAND_CONSTANT );
		stOperandAccess.parameter.set( astOperand, astConstant );
	}
	return astOperand;
}
AST CG_NewResultOperand( AST astCmdList ){
	AST astOperand=0;
	if( astCmdList > 0 ){
		stOperandAccess.alloc(1);
		astOperand = stOperandAccess.getMax();
		stOperandAccess.kind.set( astOperand, OPERAND_RESULT );
		stOperandAccess.parameter.set( astOperand, astCmdList );
	}
	return astOperand;
}
AST CG_NewVariableOperand( AST astVari ){
	AST astOperand=0;
	if( astVari > 0 ){
		stOperandAccess.alloc(1);
		astOperand = stOperandAccess.getMax();
		stOperandAccess.kind.set( astOperand, OPERAND_OBJECT );
		stOperandAccess.parameter.set( astOperand, astVari );
	}
	return astOperand;
}
AST CG_NewFunctionOperand( AST astFunc ){
	AST astOperand=0;
	if( astFunc > 0 ){
		stOperandAccess.alloc(1);
		astOperand = stOperandAccess.getMax();
		stOperandAccess.kind.set( astOperand, OPERAND_FUNCTION );
		stOperandAccess.parameter.set( astOperand, astFunc );
	}
	return astOperand;
}
VOID CG_CmdListSetType( AST astList, AST astCCType ){
	AST astLinkType = CG_ConvertTypeInfo( astCCType );
	stCmdListAccess.type.set( astList, astLinkType );
}

